package tour;

import java.util.HashMap;
import java.util.Map;

// visit calculator
public class EvalVisitor extends LabeledExprBaseVisitor<Integer> {
    // store variable or value
    Map<String, Integer> memory = new HashMap<>();

    // ID '=' expr NEWLINE
    @Override
    public Integer visitAssign(LabeledExprParser.AssignContext ctx) {
        // get left-hand side of '='
        String id = ctx.ID().getText();
        // compute value of expression on right
        int value = visit(ctx.expr());
        memory.put(id, value);
        return value;
    }

    // expr NEWLINE
    @Override
    public Integer visitPrintExpr(LabeledExprParser.PrintExprContext ctx) {
        Integer value = visit(ctx.expr());
        // print result
        System.out.println(value);
        return 0;
    }

    // INT
    @Override
    public Integer visitInt(LabeledExprParser.IntContext ctx) {
        return Integer.valueOf(ctx.INT().getText());
    }

    // ID
    @Override
    public Integer visitId(LabeledExprParser.IdContext ctx) {
        String id = ctx.ID().getText();
        if (memory.containsKey(id)) {
            return memory.get(id);
        }
        return 0;
    }

    // expr op=('*' | '/') expr
    @Override
    public Integer visitMulDiv(LabeledExprParser.MulDivContext ctx) {
        // get left subexpression
        int left = visit(ctx.expr(0));
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == LabeledExprParser.MUL) {
            return left * right;
        }
        // div
        return left / right;
    }

    // expr op=('+' | '-') expr
    @Override
    public Integer visitAddSub(LabeledExprParser.AddSubContext ctx) {
        int left = visit(ctx.expr(0));
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == LabeledExprParser.ADD) {
            return left + right;
        }
        return left - right;
    }

    // '(' expr ')'
    @Override
    public Integer visitParens(LabeledExprParser.ParensContext ctx) {
        // return child expr's value'
        return visit(ctx.expr());
    }
}
